package com.exonline.front.controller.login;

import cn.hutool.core.util.IdUtil;
import com.exonline.commons.entity.Teacher;
import com.exonline.commons.utils.TokenUtils;
import com.exonline.commons.entity.Student;
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * @desc 登录模块控制器
 * 该类负责处理与登录、注册和注销相关的请求。
 * 包括登录、注册、登出操作。
 * @author hbrj
 */
@WebServlet("/font/Login")
public class LoginServlet extends HttpServlet  {
    // 使用Jackson库进行JSON格式的响应输出
    ObjectMapper mapper = new ObjectMapper();
    // 登录业务逻辑层
    LoginService service = new LoginService();

    /**
     * @desc 1.处理 HTTP 请求方法
     * 根据请求中的 "method" 参数调用相应的处理方法：登录、注册、注销。
     *
     * @param req  HttpServletRequest 请求对象
     * @param resp HttpServletResponse 响应对象
     * @throws ServletException 如果请求处理出现错误
     * @throws IOException 如果响应时出现错误
     */
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("UTF-8");
        String method = req.getParameter("method");
        try {
            if ("login".equals(method)) {
                this.login(req, resp);
            } else if ("register".equals(method)) {
                this.register(req, resp);
            } else if ("logout".equals(method)) {
                this.logout(req, resp);
            }
        }catch (Exception e){
            throw new ServletException(e);
        }
    }

    /**
     * @desc  2.处理注册请求,响应注册结果,注册成功用户方可登录。
     * @param req  HttpServletRequest 请求对象
     * @param resp HttpServletResponse 响应对象
     * @throws IOException 如果响应时出现错误
     * @throws NoSuchAlgorithmException 如果密码加密算法不存在
     */
    private void register(HttpServletRequest req, HttpServletResponse resp) throws IOException, NoSuchAlgorithmException {
        // 获取用户输入的注册信息
        // 生成随机用户ID
        String id = IdUtil.simpleUUID();
        // 获取用户名
        String sname = req.getParameter("sname");
        // 获取手机号
        String phone = req.getParameter("phone");
        // 获取输入的密码
        String password = req.getParameter("password");
        System.out.println("sname:" + sname + "," + "phone:" + phone + "," + "password:" + password);
        Map<String, Object> map = new HashMap<>();
        // 调用服务层进行注册的操作
        int count = service.register(id, sname, phone, password);
        if (count != 0) {
            map.put("code", 200);
            map.put("msg", "注册成功");
            map.put("data", id);
            map.put("phone",phone);
            // 调用TokenUtils, 生成 Token
            String token = TokenUtils.createToken(id, sname);
            // 返回 Token
            map.put("token",token);
            //返回成功的响应
            mapper.writeValue(resp.getWriter(),map);
        }else {
            map.put("code", 201);
            map.put("msg", "注册失败,该用户名已经存在");
            map.put("data", phone);
            //返回失败的响应
            mapper.writeValue(resp.getWriter(), map);
        }
    }

    /**
     * @desc 3.处理登录请求,验证用户名和密码，登录成功后返回用户信息及 Token。
     * @param req  HttpServletRequest 请求对象
     * @param resp HttpServletResponse 响应对象
     * @throws SQLException 如果数据库操作出现错误
     * @throws IOException 如果响应时出现错误
     * @throws NoSuchAlgorithmException 如果密码加密算法不存在
     */
    private void login(HttpServletRequest req, HttpServletResponse resp) throws IOException, SQLException, NoSuchAlgorithmException {
        // 获取用户输入的手机号和密码
        String phone = req.getParameter("phone");
        String password = req.getParameter("password");
        System.out.println("phone:" + phone + "," + "password:" + password);
        // 创建一个 Map 用于返回响应数据
        Map<String, Object> map = new HashMap<>();

        //1.先以教师身份登录
        Teacher teacher = (Teacher) service.login(phone, password, "教师");
        if (teacher != null && teacher.getStatus().equals("1")) {
            // 教师状态为1（活跃），登录成功
            map.put("code", 200);
            map.put("msg", "登录成功");
            map.put("data", teacher);
            //生成Token
            String token = TokenUtils.createToken(teacher.getId(), teacher.getTname());
            //返回Token
            map.put("token",token);
            // 返回成功的响应
            mapper.writeValue(resp.getWriter(), map);
        }
        //2. 再以学生身份登录
        Student student = (Student) service.login(phone, password, "学生");
        if (student != null && student.getStatus().equals("1")) {
            // 学生状态为1（活跃），登录成功
            map.put("code", 200);
            map.put("msg", "登录成功");
            map.put("data", student);
            // 生成 Token
            String token = TokenUtils.createToken(student.getId(), student.getSname());
            map.put("token",token);
            // 返回成功的响应
            mapper.writeValue(resp.getWriter(), map);
        }
        map.put("code", 201);
        map.put("msg", "登录失败");
        map.put("data", null);
        // 返回失败的响应
        mapper.writeValue(resp.getWriter(), map);
    }

    /**
     * @desc 4.处理注销请求，注销用户会话，并返回注销结果。
     * @param req HttpServletRequest 请求对象
     * @param resp HttpServletResponse 响应对象
     */
    private void logout(HttpServletRequest req, HttpServletResponse resp) {
        try {
            // 获取当前用户的会话对象，如果不存在则创建一个新的（通常在登录成功后会创建会话来关联用户信息等）
            HttpSession session = req.getSession(false);
            if (session!= null) {
                // 使当前会话失效，清除会话中存储的所有属性信息，例如用户登录信息等
                session.invalidate();
            }

            // 可以在这里添加代码来处理清除客户端存储的token相关逻辑，比如如果token存储在Cookie中，可以按如下方式清除
            Cookie[] cookies = req.getCookies();
            if (cookies!= null) {
                for (Cookie cookie : cookies) {
                    if ("token".equals(cookie.getName())) {
                        // 设置Cookie的有效期为0，使其立即失效，相当于删除该Cookie
                        cookie.setMaxAge(0);
                        resp.addCookie(cookie);
                    }
                }
            }

            Map<String, Object> map = new HashMap<>();
            map.put("code", 200);
            map.put("msg", "注销成功");
            map.put("data", null);
            // 返回成功的响应
            mapper.writeValue(resp.getWriter(), map);
        } catch (IOException e) {
            e.printStackTrace();
            try {
                Map<String, Object> errorMap = new HashMap<>();
                errorMap.put("code", 500);
                errorMap.put("msg", "注销过程中出现错误");
                errorMap.put("data", null);
                // 返回错误响应
                mapper.writeValue(resp.getWriter(), errorMap);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}
